#include "EncodeMap.h"

EncodeMap::EncodeMap(QObject* parent)
    : QObject(parent), mBase(0), mSize(0), mBuffer(nullptr), mBufferSize(0) {}

EncodeMap::~EncodeMap() {
  if (mBuffer) DbgReleaseEncodeTypeBuffer(mBuffer);
}

void EncodeMap::setMemoryRegion(duint addr) {
  mBase = DbgMemFindBaseAddr(addr, &mSize);
  if (!mBase) return;

  if (mBuffer) DbgReleaseEncodeTypeBuffer(mBuffer);
  mBuffer = (byte*)DbgGetEncodeTypeBuffer(addr, &mBufferSize);
}

void EncodeMap::setDataType(duint va, ENCODETYPE type) {
  setDataType(va, getEncodeTypeSize(type), type);
}

void EncodeMap::setDataType(duint va, duint size, ENCODETYPE type) {
  DbgSetEncodeType(va, size, type);
  if (!mBuffer && va >= mBase && va < mBase + mSize) setMemoryRegion(va);
}

void EncodeMap::delRange(duint start, duint size) {
  DbgDelEncodeTypeRange(start, size);
}

void EncodeMap::delSegment(duint va) {
  DbgDelEncodeTypeSegment(va);
  if (mBuffer && va >= mBase && va < mBase + mSize) {
    mBuffer = nullptr;
    DbgReleaseEncodeTypeBuffer(mBuffer);
  }
}

ENCODETYPE EncodeMap::getDataType(duint addr) {
  if (!mBuffer || !inBufferRange(addr)) return enc_unknown;

  return ENCODETYPE(mBuffer[addr - mBase]);
}

duint EncodeMap::getDataSize(duint addr, duint codesize) {
  if (!mBuffer || !inBufferRange(addr)) return codesize;

  auto type = ENCODETYPE(mBuffer[addr - mBase]);

  auto datasize = getEncodeTypeSize(type);
  if (isCode(type))
    return codesize;
  else
    return datasize;
}
